package com.itguigu.auth.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itguigu.auth.mapper.SysMenuMapper;
import com.itguigu.auth.mapper.SysRoleMenuMapper;
import com.itguigu.auth.service.SysMenuService;
import com.itguigu.auth.util.MenuHelper;
import com.itguigu.common.exception.GuiguException;
import com.itguigu.model.system.SysMenu;
import com.itguigu.model.system.SysRoleMenu;
import com.itguigu.vo.system.AssginMenuVo;
import com.itguigu.vo.system.MetaVo;
import com.itguigu.vo.system.RouterVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.spi.CopyOnWrite;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 *
 */
@Service
@Slf4j
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;


    @Override
    public List<SysMenu> findNodes() {
        // 获取所有菜单的数据
        List<SysMenu> sysMenus = baseMapper.selectList(null);
//        log.info("查询的所有菜单的数据包括 : sysMenus : {}", sysMenus);

        // 构建树形数据
        List<SysMenu> resultList = MenuHelper.buildTree(sysMenus);
        return resultList;
    }

    @Override
    public boolean removeMenuById(Long id) {
        int count = (int) this.count(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getParentId, id));
        if (count > 0) {
            throw new GuiguException(201, "菜单不能删除");
        }
        baseMapper.deleteById(id);
        return false;
    }

    @Override
    public List<SysMenu> findMenuByRoleId(Long roleId) {
        // 获取全部菜单列表 : 即状态是开启的所有列表
        List<SysMenu> allSysMenuList = baseMapper.selectList(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getStatus, 1));
        // 查询 该角色在 第三方表中 对应的菜单id
        List<SysRoleMenu> sysRoleMenuList = sysRoleMenuMapper.selectList(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, roleId));
        // 转换给角色id 与菜单 对应的map
        List<Long> menuIdList = sysRoleMenuList.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList());
        // 遍历所有菜单 , 如果对应 添加标签
        allSysMenuList.forEach(permission -> {
            if (menuIdList.contains(permission.getId())) {
                // 菜单的id
                permission.setSelect(true);
            } else {
                permission.setSelect(false);
            }
        });
        return MenuHelper.buildTree(allSysMenuList);
    }

    @Override
    public void doAssign(AssginMenuVo assginMenuVo) {
        // 所有角色原菜单全部逻辑删除
        sysRoleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, assginMenuVo.getRoleId()));
        // 添加新的
        for (Long menuId : assginMenuVo.getMenuIdList()) {
            if (StringUtils.isEmpty(menuId)) {
                continue;
            }
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setRoleId(assginMenuVo.getRoleId());
            sysRoleMenu.setMenuId(menuId);
            sysRoleMenuMapper.insert(sysRoleMenu);
        }
    }

    @Override
    public List<RouterVo> findUserMenuListByUserId(Long userId) {
        List<SysMenu> sysMenusList;
        // 判断是否是管理员
        //超级管理员admin账号id为：1
        if (userId.longValue() == 1) {
            // 是超级管理员 , 查询所有
            LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SysMenu::getStatus, 1);
            queryWrapper.orderByAsc(SysMenu::getSortValue);
            sysMenusList = baseMapper.selectList(queryWrapper);
        } else {
            // userrole -> rolemenu -> menu
            sysMenusList = baseMapper.findMenuListByUserId(userId);
        }
        // 数据列表 -- 树形结构构建
        List<SysMenu> sysMenusTreeList = MenuHelper.buildTree(sysMenusList);
        // 构建指定要求的路由结构
        List<RouterVo> routerVoList = this.buildRouter(sysMenusTreeList);
        return routerVoList;
    }

    /**
     * 构建路由结构
     *
     * @param menus
     * @return
     */
    private List<RouterVo> buildRouter(List<SysMenu> menus) {
        // 创建最终数据list集合
        List<RouterVo> routers = new ArrayList<>();
        // 数据遍历
        for (SysMenu menu : menus) {
            // 创建vo对象 实例话
            RouterVo router = new RouterVo();
            router.setHidden(false); // 是否隐藏
            router.setAlwaysShow(false); // 总是展示
            router.setPath(getRouterPath(menu)); // 路由地址
            router.setComponent(menu.getComponent()); // 组件路径
            router.setMeta(new MetaVo(menu.getName(), menu.getIcon())); // 设置头信息 : 标题和图标
            // 下一层数据部分
            List<SysMenu> children = menu.getChildren();
            if (menu.getType().intValue() == 1) {
                // 该菜单类型为 1  , 即是菜单 , 1: 菜单 , 2. 页面 , 3.功能操作按钮
                // 获取 隐藏路由信息
                List<SysMenu> hiddenMenuList = children.stream()
                        .filter(item -> !StringUtils.isEmpty(item.getComponent()))
                        .collect(Collectors.toList());
                // 遍历隐藏路由 , 设置对应实例
                for (SysMenu hiddenMenu : hiddenMenuList) {
                    RouterVo hiddenRouter = new RouterVo();
                    hiddenRouter.setHidden(true);
                    hiddenRouter.setAlwaysShow(false);
                    hiddenRouter.setPath(getRouterPath(hiddenMenu));
                    hiddenRouter.setComponent(hiddenMenu.getComponent());
                    hiddenRouter.setMeta(new MetaVo(hiddenMenu.getName(), hiddenMenu.getIcon()));
                    routers.add(hiddenRouter);
                }
            } else {
                // 将 非隐藏路由 的总是显示设置修改为true
                // 判断有children
                if (!CollectionUtils.isEmpty(children)) {
                    if (children.size() > 0) {
                        // 路由显示
                        router.setAlwaysShow(true);
                    }
                    // 不为空 , 递归遍历
                    router.setChildren(buildRouter(children));
                }
            }
            routers.add(router);
        }
        return routers;
    }

    /**
     * 获取路由地址
     *
     * @param menu
     * @return
     */
    private String getRouterPath(SysMenu menu) {
        // 一级菜单需要添加/
        String routerPath = "/" + menu.getPath();
        if (menu.getParentId().intValue() != 0) {
            // 不是一级菜单
            routerPath = menu.getPath();
        }
        return routerPath;
    }

    /**
     * 获取操作按钮列表
     *
     * @param userId
     * @return
     */
    @Override
    public List<String> findUserPermsByUserId(Long userId) {
        // 判断是否是超级管理员
        List<SysMenu> sysMenuList = null;
        if (userId.longValue() == 1) {
            // 超级管理员
            LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SysMenu::getStatus, 1);
            sysMenuList = baseMapper.selectList(queryWrapper);
        } else {
            sysMenuList = baseMapper.findMenuListByUserId(userId);
        }
        // 获取到perms
        List<String> permsList = sysMenuList.stream()
                .filter(item -> item.getType() == 2)
                .map(item -> item.getPerms())
                .collect(Collectors.toList());

        return permsList;
    }
}
